package com.fuyao.cloud.admin.flow.actor;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.fuyao.cloud.flowable.entity.ActorUser;
import com.fuyao.cloud.flowable.vo.ActorInstance;
import com.fuyao.cloud.common.core.util.R;
import com.fuyao.cloud.common.security.service.CloudUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Map;
import java.util.Optional;


@Slf4j
@ActorTypeCodeAnnotation("AT_RULE")
@Component
public class ActorTypeAtRule implements ActorTypeFactory {

    @Autowired
    private RestTemplate restTemplate;

    @Override
    public List<ActorInstance> execute(CloudUser user, ActorUser actorUser, String procInstId) {
        log.info("AT_RULE : actorId:{}, procInstId:{}", actorUser.getActorId(), procInstId);

        if (ObjectUtil.isEmpty(actorUser) || StrUtil.isEmpty(actorUser.getParams())) {
            return Lists.newArrayList();
        }

        if ("y".equals(actorUser.getRemoteFlag())) {
            return getRemoteActorInstance(actorUser);
        }

        Object obj = SpringUtil.getBean(actorUser.getParams());
        if (null == obj) {
            throw new RuntimeException("未在Spring中找到" + actorUser.getActorId() + "相应的Bean。");
        }

        if (obj instanceof ActorRule) {
            ActorRule actorRule = (ActorRule) obj;
            return actorRule.execute(user, actorUser, procInstId);
        }
        return Lists.newArrayList();
    }

    private List<ActorInstance> getRemoteActorInstance(ActorUser actorUser) {
        // TODO：优化服务ID配置。
        log.info("serviceId:{},serviceUrl:{}", actorUser.getServiceId(), actorUser.getServiceUrl());

        if (StrUtil.isEmpty(actorUser.getServiceId()) || StrUtil.isEmpty(actorUser.getServiceUrl())) {
            return Lists.newArrayList();
        }

        String url = StrUtil.builder().append("http://").append(actorUser.getServiceId()).append(actorUser.getServiceUrl()).toString();
        Map<String, Object> paramsMap = JSON.parseObject(JSON.toJSONString(actorUser), new TypeReference<Map<String, Object>>() {
        });

        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
        HttpEntity<Map<String, Object>> formEntity = new HttpEntity<>(paramsMap, headers);
        R<List<ActorInstance>> result = restTemplate.postForObject(url, formEntity, R.class);
        return Optional.ofNullable(result.getData()).orElse(Lists.newArrayList());
    }
}
